
package com.gemframework.modules.prekit.flow.controller;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.gemframework.common.constant.GemModules;
import com.gemframework.model.common.BaseResultData;
import com.gemframework.model.common.PageInfo;
import com.gemframework.model.enums.ExceptionCode;
import com.gemframework.controller.BaseController;
import com.gemframework.modules.prekit.flow.entity.GemModel;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.UnsupportedEncodingException;
import java.util.List;

/**
 * @Title: ModelerController
 * @Package: com.gemframework.modules.perkit.demo
 * @Date: 2020-04-16 13:36:13
 * @Version: v1.0
 * @Description: 模型管理
 * @Author: nine QQ 769990999
 * @Copyright: Copyright (c) 2020 wanyong
 * @Company: www.gemframework.com
 */
@RestController
@RequestMapping(GemModules.PreKit.PATH_FLOW+"/models")
public class ModelerController extends BaseController {

    @Autowired
    RepositoryService repositoryService;
    @Autowired
    ObjectMapper objectMapper;

    /**
     * 创建模型
     * @param requst
     * @return
     * @throws UnsupportedEncodingException
     */
    @PostMapping("create")
    public BaseResultData create(@RequestBody GemModel requst) throws UnsupportedEncodingException {
        //初始化一个空模型
        Model model = repositoryService.newModel();
        String name = requst.getName();
        String key = requst.getKey();
        int revision = requst.getRevision();
        String description = requst.getDescription();
        String category = requst.getCategory();
        String tenantId = requst.getTenantId();

        ObjectNode modelNode = objectMapper.createObjectNode();
        modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);
        modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
        modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);

        model.setName(name);
        model.setKey(key);
        model.setMetaInfo(modelNode.toString());
        model.setCategory(category);
        model.setTenantId(tenantId);

        repositoryService.saveModel(model);
        String id = model.getId();
        //完善ModelEditorSource
        ObjectNode editorNode = objectMapper.createObjectNode();
        editorNode.put("id", "canvas");
        editorNode.put("resourceId", "canvas");
        ObjectNode stencilSetNode = objectMapper.createObjectNode();
        stencilSetNode.put("namespace","http://b3mn.org/stencilset/bpmn2.0#");
        editorNode.put("stencilset", stencilSetNode);
        repositoryService.addModelEditorSource(id,editorNode.toString().getBytes("utf-8"));
        return BaseResultData.SUCCESS(id);
    }

    /**
     * 上传模型
     * @param requst
     * @return
     * @throws UnsupportedEncodingException
     */
    @PostMapping("upload")
    public BaseResultData upload(@RequestBody GemModel requst) throws UnsupportedEncodingException {
        //初始化一个空模型
        Model model = repositoryService.newModel();
        String name = requst.getName();
        String key = requst.getKey();
        int revision = requst.getRevision();
        String description = requst.getDescription();
        String category = requst.getCategory();
        String tenantId = requst.getTenantId();

        ObjectNode modelNode = objectMapper.createObjectNode();
        modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);
        modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
        modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);

        model.setName(name);
        model.setKey(key);
        model.setMetaInfo(modelNode.toString());
        model.setCategory(category);
        model.setTenantId(tenantId);

        repositoryService.saveModel(model);
        String id = model.getId();
        //完善ModelEditorSource
        ObjectNode editorNode = objectMapper.createObjectNode();
        editorNode.put("id", "canvas");
        editorNode.put("resourceId", "canvas");
        ObjectNode stencilSetNode = objectMapper.createObjectNode();
        stencilSetNode.put("namespace","http://b3mn.org/stencilset/bpmn2.0#");
        editorNode.put("stencilset", stencilSetNode);
        repositoryService.addModelEditorSource(id,editorNode.toString().getBytes("utf-8"));
        return BaseResultData.SUCCESS(id);
    }


    /**
     * 发布模型为流程定义
     * @param id
     * @return
     * @throws Exception
     */

    @PostMapping("deployment")
    public BaseResultData deploy(String id) throws Exception {

        //获取模型
        Model modelData = repositoryService.getModel(id);
        byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());

        if (bytes == null) {
            return BaseResultData.ERROR(ExceptionCode.MODEL_IS_EMPTY);
        }

        JsonNode modelNode = new ObjectMapper().readTree(bytes);
        BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
        if(model.getProcesses().size()==0){
            return BaseResultData.ERROR(ExceptionCode.MODEL_LACK_OF_MAIN_FLOW);
        }
        byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);

        //发布流程
        String processName = modelData.getName() + ".bpmn20.xml";
        Deployment deployment = repositoryService.createDeployment()
                .name(modelData.getName())
                .category(modelData.getCategory())
                .tenantId(modelData.getCategory())
                .addString(processName, new String(bpmnBytes, "UTF-8"))
                .deploy();
        modelData.setDeploymentId(deployment.getId());
        repositoryService.saveModel(modelData);

        return BaseResultData.SUCCESS();
    }


    /**
     * 分页获取模型数据
     * @param pageInfo
     * @param name
     * @return
     */
    @GetMapping("/page")
    public BaseResultData page(PageInfo pageInfo,String name) {
        List<Model> list;
        long count;
        if(StringUtils.isNotBlank(name)){
            list = repositoryService.createModelQuery()
                    .modelNameLike(name).orderByLastUpdateTime().desc()
                    .listPage(pageInfo.getLimit().intValue() * (pageInfo.getPage().intValue() - 1), pageInfo.getLimit().intValue());
            count = repositoryService.createModelQuery().modelNameLike(name).count();
        }else{
            list = repositoryService.createModelQuery().orderByLastUpdateTime().desc()
                    .listPage(pageInfo.getLimit().intValue() * (pageInfo.getPage().intValue() - 1), pageInfo.getLimit().intValue());
            count = repositoryService.createModelQuery().count();
        }
        return BaseResultData.SUCCESS(list,count);
    }

    /**
     * 删除模型数据
     * @param id
     * @return
     */
    @PostMapping("/delete")
    public BaseResultData delete(String id){
        repositoryService.deleteModel(id);
        return BaseResultData.SUCCESS();
    }

    /**
     * 查看模型信息
     * @param id
     * @return
     */
    @GetMapping("/info")
    public BaseResultData info(String id) {
        Model model = repositoryService.createModelQuery().modelId(id).singleResult();
        return BaseResultData.SUCCESS(model);
    }


}
